﻿using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using ChatClient.Models;
using ChatClient.Services;
using DotnetUtil.Extensions;
using DotnetUtil.Services;
using HandyControl.Controls;
using Prism.Commands;
using Prism.Mvvm;

namespace ChatClient.ViewModels
{
    internal class ChatViewModel : BindableBase
    {
        #region 依赖属性

        public DelegateCommand<ChatMessage> OpenImageCommand { get; set; }
        public DelegateCommand TypingCommand { get; set; }
        public DelegateCommand SendImageMessageCommand { get; set; }
        public DelegateCommand SendTextMessageCommand { get; set; }

        public ObservableCollection<Participant> Participants { get; }

        public string? UserName
        {
            get => _userName;
            set => SetProperty(ref _userName, value);
        }

        public string? TextMessage
        {
            get => _textMessage;
            set => SetProperty(ref _textMessage, value);
        }

        public string? ProfilePic
        {
            get => _profilePic;
            set => SetProperty(ref _profilePic, value);
        }

        public bool IsConnected
        {
            get => _isConnected;
            set => SetProperty(ref _isConnected, value);
        }

        public bool IsLoggedIn
        {
            get => _isLoggedIn;
            set => SetProperty(ref _isLoggedIn, value);
        }

        public Participant? SelectedParticipant
        {
            get => _selectedParticipant;
            set
            {
                SetProperty(ref _selectedParticipant, value);
                if (SelectedParticipant is { HasSentNewMessage: true })
                {
                    SelectedParticipant.HasSentNewMessage = false;
                }
            }
        }

        private string? _userName;
        private string? _textMessage;
        private string? _profilePic;
        private bool _isConnected;
        private bool _isLoggedIn;
        private Participant? _selectedParticipant;

        #endregion

        private readonly ILogService _logService;
        private readonly IChatService _chatService;
        private readonly IDialogService _dialogService;

        public ChatViewModel(
            ILogService logService,
            IChatService chatService,
            IDialogService dialogService,
            ISessionService sessionService
        )
        {
            _logService = logService;
            _chatService = chatService;
            _dialogService = dialogService;

            OpenImageCommand = new DelegateCommand<ChatMessage>(OnOpenImage);
            TypingCommand = new DelegateCommand(OnTypingAsync);
            SendImageMessageCommand = new DelegateCommand(OnSendImageMessageAsync);
            SendTextMessageCommand = new DelegateCommand(OnSendTextMessageAsync);

            Participants = sessionService.Participants;
            IsConnected = sessionService.IsConnected;
            //MockData();

            sessionService.NewTextMessage += OnNewTextMessage;
            sessionService.NewImageMessage += OnNewImageMessage;
            sessionService.IsConnectedChanged += OnIsConnectedChanged;
        }

        private void MockData()
        {
            var someChatter = new ObservableCollection<ChatMessage>();
            someChatter.Add(new ChatMessage
            {
                Author = "Batman",
                Message = "What do you think about the Batmobile?",
                Time = DateTime.Now,
                IsOriginNative = true
            });
            someChatter.Add(new ChatMessage
            {
                Author = "Batman",
                Message = "Coolest superhero ride?",
                Time = DateTime.Now,
                IsOriginNative = true
            });
            someChatter.Add(new ChatMessage
            {
                Author = "Superman",
                Message = "Only if you don't have superpowers :P",
                Time = DateTime.Now
            });
            someChatter.Add(new ChatMessage
            {
                Author = "Batman",
                Message = "I'm rich. That's my superpower.",
                Time = DateTime.Now,
                IsOriginNative = true
            });
            someChatter.Add(new ChatMessage
            {
                Author = "Superman",
                Message =
                    ":D Lorem Ipsum something blah blah blah blah blah blah blah blah. Lorem Ipsum something blah blah blah blah.",
                Time = DateTime.Now
            });
            someChatter.Add(new ChatMessage
            {
                Author = "Batman",
                Message = "I have no feelings",
                Time = DateTime.Now,
                IsOriginNative = true
            });
            someChatter.Add(new ChatMessage
            {
                Author = "Batman",
                Message = "How's Martha?",
                Time = DateTime.Now,
                IsOriginNative = true
            });

            Participants.Add(new Participant
                { Name = "Superman", Chatter = someChatter, IsTyping = true, IsLoggedIn = true });
            Participants.Add(new Participant { Name = "Wonder Woman", Chatter = someChatter, IsLoggedIn = false });
            Participants.Add(new Participant { Name = "Aquaman", Chatter = someChatter, HasSentNewMessage = true });
            Participants.Add(new Participant
                { Name = "Captain Canada", Chatter = someChatter, HasSentNewMessage = true });
            Participants.Add(new Participant { Name = "Iron Man", Chatter = someChatter, IsTyping = true });

            SelectedParticipant = Participants.First();
        }

        private void OnOpenImage(ChatMessage message)
        {
            var image = message.Picture;
            if (string.IsNullOrEmpty(image) || !File.Exists(image))
            {
                return;
            }

            //打开图片
            new ImageBrowser(new Uri(image)) { Topmost = false }.Show();
        }

        private async void OnTypingAsync()
        {
            if (SelectedParticipant is { IsLoggedIn: true })
            {
                await TypingAsync();
            }
        }

        private async Task TypingAsync()
        {
            if (SelectedParticipant == null || string.IsNullOrWhiteSpace(SelectedParticipant.Name))
            {
                return;
            }

            try
            {
                await _chatService.TypingAsync(SelectedParticipant.Name);
            }
            catch (Exception e)
            {
                _logService.Error($"发送Typing消息失败：{e.GetFullMessage()}");
            }
        }

        private async void OnSendImageMessageAsync()
        {
            if (IsConnected && SelectedParticipant != null && SelectedParticipant.IsLoggedIn)
            {
                await SendImageMessageAsync();
            }
        }

        private async void OnSendTextMessageAsync()
        {
            if (IsConnected && SelectedParticipant is { IsLoggedIn: true })
            {
                await SendTextMessageAsync();
            }
        }

        private async Task SendImageMessageAsync()
        {
            if (SelectedParticipant == null || string.IsNullOrWhiteSpace(SelectedParticipant.Name))
            {
                return;
            }

            var pic = _dialogService.OpenFile("Select image file", "Images (*.jpg;*.png)|*.jpg;*.png");
            if (string.IsNullOrEmpty(pic))
            {
                return;
            }

            var img = await Task.Run(() => File.ReadAllBytes(pic));

            try
            {
                await _chatService.SendUniCastMessageAsync(SelectedParticipant.Name, img);
            }
            catch (Exception e)
            {
                _logService.Error($"发送Image消息失败：{e.GetFullMessage()}");
            }
            finally
            {
                var message = new ChatMessage
                    { Author = UserName, Picture = pic, Time = DateTime.Now, IsOriginNative = true };
                SelectedParticipant?.Chatter.Add(message);
            }
        }

        private async Task SendTextMessageAsync()
        {
            if (SelectedParticipant == null ||
                string.IsNullOrWhiteSpace(SelectedParticipant.Name) ||
                string.IsNullOrWhiteSpace(TextMessage))
            {
                return;
            }

            try
            {
                var recipient = SelectedParticipant.Name;
                await _chatService.SendUniCastMessageAsync(recipient, TextMessage);
            }
            catch (Exception e)
            {
                _logService.Error($"发送Text消息失败：{e.GetFullMessage()}");
            }
            finally
            {
                var msg = new ChatMessage
                {
                    Author = UserName,
                    Message = _textMessage,
                    Time = DateTime.Now,
                    IsOriginNative = true
                };
                SelectedParticipant.Chatter.Add(msg);
                TextMessage = string.Empty;
            }
        }

        private void OnNewTextMessage(Participant sender)
        {
            if (!(SelectedParticipant != null && sender.Name == SelectedParticipant.Name))
            {
                sender.HasSentNewMessage = true;
            }
        }

        private void OnNewImageMessage(Participant sender)
        {
            if (!(SelectedParticipant != null && sender.Name == SelectedParticipant.Name))
            {
                sender.HasSentNewMessage = true;
            }
        }

        private void OnIsConnectedChanged(bool value)
        {
            Application.Current?.Dispatcher.BeginInvoke(new Action(() => { IsConnected = value; }));
        }
    }
}
